﻿using HT.Future.Common;
using HT.Future.Entities;
using HT.Future.IService;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.Extensions.Logging;
using NLog.LayoutRenderers.Wrappers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HT.Future.Service
{
    public class ProductService : BaseService<Product>, IProductService
    {
        private ILogger<ProductService> _logger;
        public ProductService(HtDbContext dbContext, ILogger<ProductService> logger) : base(dbContext)
        {
            _logger = logger;
        }

        public async Task<bool> IsExistProductTypeAsync(string name)
        {
            return await DbContext.Set<ProductType>().AnyAsync(a => a.Name == name);
        }

        public async Task<bool> IsExistProductTypeAsync(int productTypeId)
        {
            return await TableNoTracking.AnyAsync(a => a.ProductTypeId == productTypeId);
        }

        public async Task GenerateProductTypeAsync(IEnumerable<ProductType> types)
        {
            var entities = await DbContext.Set<ProductType>().ToListAsync();
            var adds = types.Where(a => a.Flag == EntitySign.Add);
            var updates = types.Where(a => a.Flag == EntitySign.Update);
            var deletes = types.Where(a => a.Flag == EntitySign.Delete);
            adds.ForEach(a => a.CreateTime = DateTime.Now);
            await DbContext.AddRangeAsync(adds);
            updates.ForEach(a =>
            {
                var entity = entities.FirstOrDefault(b => b.Id == a.Id);
                entity.Name = a.Name;
                entity.Sort = a.Sort;
            });
            deletes.ForEach(a =>
            {
                var entity = entities.FirstOrDefault(b => b.Id == a.Id);
                DbContext.Remove(entity);
            });
            await DbContext.SaveChangesAsync();
        }

        public async Task<List<Product>> GetProductsAsync(int typeId, int status, string key, PagingQuery paging)
        {
            var query = Table.Where(a => a.Status != ProductStatus.Delete);
            if (typeId > 0)
            {
                query = query.Where(a => a.ProductTypeId == typeId);
            }
            if (status != 99)
            {
                query = query.Where(a => a.Status == (ProductStatus)status);
            }
            if (!string.IsNullOrEmpty(key))
            {
                query = query.Where(a => a.Name.Contains(key));
            }
            paging.RecordCount = await query.CountAsync();
            var list = await query
                .Include(a => a.Attributes)
                .Include(a => a.Images)
                .AsNoTracking()
                .OrderBy(a => a.Sort)
                .Skip(paging.Skip)
                .Take(paging.PageSize)
                .ToListAsync();
            return list;
        }

        public async Task<int> GetProductMaxSortAsync(int typeId)
        {
            var entity = await TableNoTracking.Where(a => a.ProductTypeId == typeId).OrderByDescending(a => a.Sort).FirstOrDefaultAsync();
            return entity?.Sort ?? 0;
        }

        public async Task<Product> CreateProductAsync(Product product)
        {
            var now = DateTime.Now;
            product.CreateTime = now;
            if (string.IsNullOrEmpty(product.Code))
            {
                product.Code = await GenerateProductCodeAsync();
            }
            product.Pinyin = product.Name.ToPinyin();
            product.FirstLetter = product.Name.ToFirstPinyin();
            product.Status = ProductStatus.Sale;
            product.PublishTime = DateTime.Now;
            if (product.Images != null)
            {
                product.Logo = product.Images.FirstOrDefault()?.Name;
            }  
            product.Images?.ForEach(a => a.CreateTime = now);
            product.Attributes?.ForEach(a => a.CreateTime = now);
            await AddAsync(product);
            return product;
        }

        public async Task<Product> UpdateProductAsync(Product product)
        {
            var now = DateTime.Now;
            var entity = await GetByIdAsync(product.Id);
            var attrs = await DbContext.Set<ProductAttribute>().Where(a => a.ProductId == product.Id).ToListAsync();
            var images = await DbContext.Set<ProductImage>().Where(a => a.ProductId == product.Id).ToListAsync();
            entity.Name = product.Name;
            entity.Pinyin = product.Name.ToPinyin();
            entity.FirstLetter = product.Name.ToFirstPinyin();
            entity.Description = product.Description;
            entity.UnitName = product.UnitName;
            entity.Price = product.Price;
            entity.Stock = product.Stock;
            entity.UPC = product.UPC;
            entity.SKU = product.SKU;
            entity.ModifyTime = DateTime.Now;
            entity.IsDiscount = product.IsDiscount;
            entity.Sort = product.Sort;
            entity.ProductTypeId = product.ProductTypeId;

            // 保存业务属性
            attrs.ForEach(attr =>
            {
                var item = product.Attributes?.FirstOrDefault(a => a.Id == attr.Id);
                if (item == null)
                {
                    DbContext.Remove(attr);
                }
                else
                {
                    attr.Title = item.Title;
                    attr.Desc = item.Desc;
                }
            });
            var notSaveAttrs = product.Attributes?.Where(a => a.Id == 0);
            if (notSaveAttrs != null)
            {
                notSaveAttrs.ForEach(a =>
                {
                    a.ProductId = product.Id;
                    a.CreateTime = DateTime.Now;
                });
                await DbContext.AddRangeAsync(notSaveAttrs);
            }

            // 保存图片
            images.ForEach(image =>
            {
                var item = product.Images?.FirstOrDefault(a => a.Id == image.Id);
                if (item == null)
                {
                    DbContext.Remove(image);
                }
            });
            var notSaveImages = product.Images?.Where(a => a.Id == 0);
            if (notSaveImages != null)
            {
                notSaveImages.ForEach(a =>
                {
                    a.ProductId = product.Id;
                    a.CreateTime = DateTime.Now;
                });
                await DbContext.AddRangeAsync(notSaveImages);
            }
            entity.Logo = product.Images?.FirstOrDefault()?.Name;

            await DbContext.SaveChangesAsync();

            entity.Images = product.Images;
            entity.Attributes = product.Attributes;

            return entity;
        }



        /// <summary>
        /// 生成商品编码
        /// </summary>
        /// <returns></returns>
        private async Task<string> GenerateProductCodeAsync()
        {
            var code = string.Empty;
            var now = DateTime.Now;
            while (true)
            {
                code = $"80{now.Year}0{UtilHelper.RandomNumber(4)}{now:MMdd}0{UtilHelper.RandomNumber(4)}";
                var exist = await TableNoTracking.AnyAsync(a => a.Code == code);
                if (!exist) break;
            }
            return code;
        }
    }
}
